package punchdownloader.util;

import java.net.URL;
import java.util.ArrayList;
import org.apache.log4j.Logger;
import org.htmlparser.Node;
import org.htmlparser.Parser;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.tags.Div;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeIterator;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
import punchdownloader.Modelos.Anime;

/**
 * Essa classe é responsavel por todos os tipos de metodos para manipular os links.
 * Deis de separar até buscar da pagina.
 * @author Kennedy
 */
public class LinksTools extends Thread {

    private static Logger log = Logger.getLogger("----> LINKS <----");

    /**
     * Contrutor padrão.
     */
    public LinksTools() {
    }

    @Override
    public void run() {
    }

    /**
     * Pega todos os links dos episodios do anime em questão.
     * @param anime Anime que tem os links da paginas de episodios.
     */
    public static void getLinks(Anime anime) {
        try {
            Parser p = new Parser("http://www.punchsub.com/listar/125/episodios/hd/1");
            NodeIterator tudo = p.elements();
            Node a;
            a = tudo.nextNode();
            a = tudo.nextNode();
            a = tudo.nextNode();
            String s = a.toHtml();
            String x[];

            x = s.split("<span class=\"listagemEp\">");
            String o;
            String z[];
            String epi;
            URL url;
            String[] link;
            for (int i = 0; i < x.length; i++) {
                if (x[i].startsWith("Episódio")) {
                    o = x[i].substring(0, x[i].indexOf("</div>"));
                    z = o.split("<a href=\"");
                    link = new String[z.length - 1];
                    epi = z[0].substring(0, z[0].indexOf("</"));

                    for (int j = 1; j < z.length - 1; j++) {
                        try {
                            Parser pl = new Parser(z[j].substring(0, z[j].indexOf("\"")));
                            System.out.println(pl.getURL());
                        } catch (Exception ex) {
                            log.error("Erro ao tentar pegar link: ");
                            log.debug("getLinks\n" + ex);
                        }
                    }
                }
            }
            System.exit(0);

        } catch (ParserException ex) {
            log.error("Erro ao pesquisar na pagina");
            log.debug("getLinks +\n" + ex);
        }


    }

    /** 
     * Esse metodo baixa a sinopse de todos os animes
     * e atualiza os arrays
     * @param lista_de_animes ArrayList<Anime> - uma array list de animes
     */
    public static void getSinopse(ArrayList<Anime> lista_de_animes) {

        for (int i = 0; i < lista_de_animes.size(); i++) {
            log.info("Inicializando download de sinopses...");
            log.info("Total de animes: " + lista_de_animes.size());
            try {
                Parser p = new Parser(lista_de_animes.get(i).getEpisode_page());
                NodeList links = p.extractAllNodesThatMatch(new TagNameFilter("div"));
                Div div;
                String s = "";
                for (int j = 0; j < links.size(); j++) {
                    log.info("Pegando sinopse anime " + (j + 1) + " de " + lista_de_animes.size());
                    div = (Div) links.elementAt(j);
                    s = "";
                    try {
                        if (div.getAttribute("class").contains("listagemBox")) {
                            s = div.getStringText().substring(div.getStringText().lastIndexOf("</div>") + 6);
                            if (!s.contains("<d")) {
                                lista_de_animes.get(i).setSinopse(s);
                                System.out.println("Anime: " + lista_de_animes.get(i).getNome() + "\nSinopse: " + lista_de_animes.get(i).getSinopse());
                            }
                        }
                    } catch (Exception e) {
                        continue;
                    }
                }
            } catch (ParserException ex) {
                log.error("Erro ao se conectar no servidor...");
                log.debug(ex);
                continue;
            }
        }


    }

    /**
     * Esse método preenche todos os links para as paginas dos animes.
     * Ex. link para pagina em HD ou MP4 ou FULLHD
     * @param lista_de_animes ArrayList - Um ArrayList de objetos Anime para preencher, os objetos já devem ter pelomenos 1 link.
     */
    private void completarLinksEpisodios(ArrayList<Anime> lista_de_animes) {

        try {
            for (int j = 0; j < lista_de_animes.size(); j++) {
                Parser p = new Parser(lista_de_animes.get(j).getEpisode_page());
                NodeList links = p.extractAllNodesThatMatch(new TagNameFilter("a"));
                LinkTag lk;
                for (int i = 0; i < links.size(); i++) {
                    lk = (LinkTag) links.elementAt(i);
                    if (lk.extractLink().contains("listar/" + lista_de_animes.get(j).getId() + "/episodios") && lk.extractLink().matches("^.*[0-9]+$")) {
                        setEpiLink(lk, lista_de_animes.get(j));
                    }
                }
            }


        } catch (ParserException ex) {
        }
    }

    /**
     * Esse metododo cria objetos <b>Anime</b> com as informações basicas, Nome, ID, e um link para pagina dele.
     * @param url_pagina Uma string contendo o endereço da pagina para pegar os links do projetos.
     * @param lista_de_animes Um ArrayList de Anime para que possam ser criados os animes com informações basicas.
     */
    private void getLinkFromPage(String url_pagina, ArrayList<Anime> lista_de_animes) {
        Anime anm;

        try {
            Parser p = new Parser(url_pagina);
            NodeList links = p.extractAllNodesThatMatch(new TagNameFilter("a"));
            LinkTag lk;
            int id;

            for (int i = 0; i < links.size(); i++) {
                lk = (LinkTag) links.elementAt(i);

                if (lk.extractLink().contains("listar") && lk.extractLink().contains("episodio") && !lk.getLinkText().isEmpty()) {
                    id = Integer.parseInt(lk.extractLink().substring(lk.extractLink().indexOf("listar/") + 7, lk.extractLink().indexOf("/epis")));
                    if (!animeExists(id, lista_de_animes)) {
                        anm = new Anime(lk.getLinkText());
                        anm.setId(String.valueOf(id));
                    } else {
                        continue;
                    }

                    setEpiLink(lk, anm);

                    lista_de_animes.add(anm);
                }
            }
        } catch (ParserException ex) {
            //Erro ao tentar fazer download do source da pagina
        }
    }

    /**
     * Retorna os links das paginas do projeto.
     * @param url_projeto String contendo o link para a pagina principal de projetos.
     * @return Um Array de String contendo os links das paginas.
     */
    private String[] getPaginaLinks(String url_projeto) {
        String s = "";
        try {
            Parser p = new Parser(url_projeto);
            NodeList links = p.extractAllNodesThatMatch(new TagNameFilter("a"));
            LinkTag lk;
            for (int i = 0; i < links.size(); i++) {
                lk = (LinkTag) links.elementAt(i);
                if (lk.extractLink().contains("nome/todos/") && lk.extractLink().matches("^.*[0-9]+$")) {
                    if (!s.contains(lk.extractLink())) {
                        s += lk.extractLink() + "#!#";
                    }
                }
            }

        } catch (ParserException ex) {
            //Erro ao fazer download do fonte da pagina
        } finally {
            return s.split("#!#");
        }

    }

    /**
     * Checa se determinado anime já está na lista.
     * @param id Int com o id do anime que deseja saber se já está na lista.
     * @param lista_de_animes ArrayList de <b>Anime</b> contendo os animes que já foram adicionados para pesquisa.
     * @return  <b>True</b> caso o anime esteja e <b>False</b> caso não esteja na lista.
     */
    private boolean animeExists(int id, ArrayList<Anime> lista_de_animes) {
        if (lista_de_animes.size() > 0) {
            for (Anime a : lista_de_animes) {
                if (Integer.parseInt(a.getId()) == id) {
                    return true;
                }
            }
            return false;
        } else {
            return false;
        }

    }

    /**
     * Adiciona o link ao <b>Anime</b>
     * @param lk Um LinkTag contendo o link.
     * @param anime Um objeto tipo <b>Anime</b> que vai receber o link.
     */
    private void setEpiLink(LinkTag lk, Anime anime) {
        if (lk.extractLink().contains("/hd/")) {
            anime.setLink_hd(lk.extractLink());
        } else if (lk.extractLink().contains("/fullhd/")) {
            anime.setLink_fullhd(lk.extractLink());
        } else if (lk.extractLink().contains("/sd/")) {
            anime.setLink_sd(lk.extractLink());
        } else if (lk.extractLink().contains("/mp4/")) {
            anime.setLink_mp4(lk.extractLink());
        } else if (lk.extractLink().contains("/slq/")) {
            anime.setLink_slq(lk.extractLink());
        }
    }
}
